package legumes.client.ui.widgets.map;

import java.util.ArrayList;
import java.util.List;

import legumes.client.resources.PNResources;

import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.event.MarkerDragEndHandler;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.geom.LatLngBounds;
import com.google.gwt.maps.client.overlay.Icon;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.maps.client.overlay.Polygon;

public class MapDrawingCircleUtils {
	
	private Polygon circleLine;
	private Marker markerCircleResizer;
	private MapWidget map;
	private LatLng center;
	private int radius;
	private boolean isEditable;
	private static final String circleColor = "#0a00a5";
//	private final Marker marker;
	
	public MapDrawingCircleUtils(MapWidget map_, LatLng center_, int radius_, boolean isEditable_){
		map = map_;
		center = center_;
		radius = radius_;
		isEditable = isEditable_;
		
//		// Add a marker
//		MarkerOptions mo = MarkerOptions.newInstance();
//		mo.setDraggable(isEditable);
//		marker = new Marker(center_, mo);
//		marker.addMarkerDragEndHandler(new MarkerDragEndHandler(){
//
//			@Override
//			public void onDragEnd(MarkerDragEndEvent event) {
//				drawCircle();
//			}
//			
//		});
//		map.addOverlay(marker);
	}
	
	public MapDrawingCircleUtils(MapWidget map_, LatLng center_, int radius_){
		this(map_, center_, radius_, false);
	}
	
	public void drawCircle() {
		if (circleLine != null) {
			map.removeOverlay(circleLine);
		}
		
		final LatLngBounds bounds = LatLngBounds.newInstance();
		List<LatLng> circlePoints = new ArrayList<LatLng>();
//		int circleRadius = (radius);// /1000); //km
		double d = radius / 6378.8; // radians : Earth radius = 6378.8km
		double lat1 = center.getLatitudeRadians();// (Math.PI / 180) * center.getLatitude(); // radians
		double lng1 = center.getLongitudeRadians(); //(Math.PI / 180) * center.getLongitude(); // radians
		for (double a = 0; a < 361; a=a+5) {
			double tc = (Math.PI / 180) * a;
			double y = Math.asin(Math.sin(lat1) * Math.cos(d) + Math.cos(lat1)
					* Math.sin(d) * Math.cos(tc));
			double dlng = Math.atan2(
					Math.sin(tc) * Math.sin(d) * Math.cos(lat1), Math.cos(d)
							- Math.sin(lat1) * Math.sin(y));
			double x = ((lng1 - dlng + Math.PI) % (2 * Math.PI)) - Math.PI; // MOD
																			// function
			LatLng point = LatLng.newInstance(y * (180 / Math.PI), x
					* (180 / Math.PI));
			circlePoints.add(point);
			bounds.extend(point);
		}
		
		if(isEditable){
			LatLng quartPoint = LatLng.newInstance(center.getLatitude(), circlePoints.get( ((int)Math.floor(circlePoints.size()/4))*3 ).getLongitude());
			if(markerCircleResizer==null){
				Icon ic = Icon.DEFAULT_ICON;
				ic.setImageURL( PNResources.INSTANCE.gmapResizerCircleMarkerIcon().getURL());
				
				MarkerOptions mo = MarkerOptions.newInstance(ic);
				mo.setDraggable(isEditable);
				
				markerCircleResizer = new Marker(quartPoint, mo);
				markerCircleResizer.addMarkerDragEndHandler(new MarkerDragEndHandler(){
		
					@Override
					public void onDragEnd(MarkerDragEndEvent event) {
						LatLng senderLatLng = markerCircleResizer.getLatLng();
						double newRadius = computeDistance(center, senderLatLng);
						//Update Radius
						int oldRadius = radius;
						radius = (int)newRadius;
						drawCircle();
						onCircleResized(oldRadius, radius);
					}
					
				});
				markerCircleResizer.setLatLng(quartPoint);
				map.addOverlay(markerCircleResizer);
			}
			markerCircleResizer.setLatLng(quartPoint);
		}
		
//		if (d < 1.5678565720686044) {
//			circleLine = new Polygon(circlePoints.toArray(new LatLng[0]),
//					color, 2, 1, color, 0.25);
//		} else {
			circleLine = new Polygon(circlePoints.toArray(new LatLng[0]),
					circleColor, 2, 1, circleColor, 0.25);
//		}
		map.addOverlay(circleLine);
		
//		Timer t = new Timer() {
//		      public void run() {
//		    	  map.setZoomLevel(map.getBoundsZoomLevel(bounds));
//				  map.setCenter(center);
//		      }
//		    };
//
//		    // Schedule the timer to run once in 5 seconds.
//		    t.schedule(400);
//		    Marker mcenter = new Marker(center);
//			map.addOverlay(mcenter);
			
	}
	
	protected void onCircleResized(int oldRadius_, int newRadius_){
		
	}
	
	public static double computeDistance(LatLng source_, LatLng dest_){
		return Math.acos(Math.sin(source_.getLatitudeRadians())*
				Math.sin(dest_.getLatitudeRadians())+
				Math.cos(source_.getLatitudeRadians())*Math.cos(dest_.getLatitudeRadians())*
				Math.cos(dest_.getLongitudeRadians()-source_.getLongitudeRadians()) )*6371;
	}

	public void setCenter(LatLng center_){
		center = center_;
	}
	
	public LatLng getCenter(){
		return center;
	}
	
	public void clearCreatedMapOverlays() {
		if (circleLine != null) {
			map.removeOverlay(circleLine);
			circleLine=null;
		}
		if( markerCircleResizer != null ){
			map.removeOverlay(markerCircleResizer);
			markerCircleResizer=null;
		}
	}

	public void setRadius(int radius_) {
		radius = radius_;
	}
}
